package com.company;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.MarshallingContext;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.io.xml.StaxDriver;
import lombok.AllArgsConstructor;
import lombok.Data;

public class P037_XStream {

    public static void main(String[] args) {
        P037_XStream tester = new P037_XStream();
        XStream xstream = new XStream(new StaxDriver());
        Student student = tester.getStudentDetails();
        xstream.autodetectAnnotations(true);
        xstream.registerConverter(new StudentConverter()); // 注册转换器
        // Object to XML Conversion
        String xml = xstream.toXML(student);
        System.out.println(xml);
    }

    public void method() {
        Person person = new Person();
        person.setName("ABC");
        person.setAge(12);
        XStream xstream = new XStream();
        xstream.alias("student", Person.class);
        String s = xstream.toXML(person);
        System.out.println(s);

        // 解决Security framework of XStream not explicitly initialized, using predefined black list on your own risk.
        XStream.setupDefaultSecurity(xstream);
        xstream.allowTypes(new Class[]{Person.class});

        Person person1 = (Person) xstream.fromXML(s);
        System.out.println(person1);
    }

    @Data
    public static class Person {
        private String name;

        private Integer age;
    }

    private Student getStudentDetails() {
        return new Student("Mahesh", "Parashar");
    }


    @XStreamAlias("student")
    public static class Student {

        @XStreamAlias("name")
        private final Name studentName;

        public Student(String firstName, String lastName) {
            this.studentName = new Name(firstName, lastName);
        }

        public Name getName() {
            return studentName;
        }
    }

    @Data
    @AllArgsConstructor
    public static class Name {
        private String firstName;
        private String lastName;
    }

    public static class StudentConverter implements Converter {

        @Override
        public void marshal(Object value, HierarchicalStreamWriter writer,
                            MarshallingContext context) {
            Student student = (Student) value;
            writer.startNode("name");
            writer.setValue(student.getName().getFirstName() + ","
                    + student.getName().getLastName());
            writer.endNode();
        }


        @Override
        public Object unmarshal(HierarchicalStreamReader reader,
                                UnmarshallingContext context) {
            reader.moveDown();
            String[] nameparts = reader.getValue().split(",");
            Student student = new Student(nameparts[0], nameparts[1]);
            reader.moveUp();
            return student;
        }

        @Override
        public boolean canConvert(Class object) {
            return object.equals(Student.class);
        }
    }
}
